'use strict';
/**
 * Created by FreezeSoul on 2016/3/10.
 */
define([
        'jquery',
        'underscore',
        'loglevel',
        'adConfig',
    ],
    function ($, _, log, adConfig) {


        /*
         * UUID
         * */
        function newUUID() {
            function s4() {
                return Math.floor((1 + Math.random()) * 0x10000)
                    .toString(16)
                    .substring(1);
            }

            return s4() + s4() + s4() + s4() + s4() + s4() + s4() + s4();
        }

        /*
         * 映射属性及Option
         * */
        function linkOption(properties, option) {
            _.each(properties, function (property) {
                if (property.enable && property.type != 'group' && property.link) {
                    if ($.type(property.link) === "string") {
                        var index = 0;
                        var reference = option;
                        var links = property.link.split('.');
                        while (index < (links.length - 1)) {
                            var link = links[index];
                            if (reference[link] === undefined) {
                                reference[link] = {};
                            }
                            reference = reference[link];
                            index++;
                        }
                        reference[links[links.length - 1]] = property.value;
                    } else if ($.type(property.link) === "function") {
                        try {
                            property.link.call(property, option)
                        } catch (e) {
                            log.error(e);
                        }
                    }
                }
                if (property.link && property.type == 'group' && property.items.length > 0) {
                    if ($.type(property.link) === "string") {
                        var index = 0;
                        var reference = option;
                        var links = property.link.split('.');
                        while (index < (links.length - 1)) {
                            var link = links[index];
                            if (reference[link] === undefined) {
                                reference[link] = {};
                            }
                            reference = reference[link];
                            index++;
                        }
                        var arrayPropertyName = links[links.length - 1];
                        if (!$.isArray(reference[arrayPropertyName])) {
                            reference[arrayPropertyName] = [];
                        }
                        for (var i = 0; i < (property.items.length - reference[arrayPropertyName].length); i++) {
                            var innerOption = {};
                            reference[arrayPropertyName].push(innerOption);
                        }
                        if (reference[arrayPropertyName].length > property.items.length) {
                            reference[arrayPropertyName].splice(property.items.length, reference[arrayPropertyName].length - property.items.length);
                        }
                        for (var i = 0; i < reference[arrayPropertyName].length; i++) {
                            //确保link是function的情况有值
                            _.each(property.items[i].option, function (itemOption) {
                                var defaultOption = _.findWhere(property.option, {id: itemOption.id});
                                if (defaultOption) {
                                    itemOption.link = defaultOption.link;
                                }
                            });
                            linkOption(property.items[i].option, reference[arrayPropertyName][i])
                        }
                    } else if ($.type(property.link) === "function") {
                        try {
                            property.link.call(property, option);
                        } catch (e) {
                            log.error(e);
                        }
                        for (var i = 0; i < property.items.length; i++) {
                            var item = property.items[i];
                            //确保link是function的情况有值
                            _.each(property.items[i].option, function (itemOption) {
                                var defaultOption = _.findWhere(property.option, {id: itemOption.id});
                                if (defaultOption) {
                                    itemOption.link = defaultOption.link;
                                }
                            });
                            //Group Link为Function时，子item也必须为Function，传入的Option为根Option
                            if (_.every(item.option, function (itemOption) {
                                return $.type(itemOption.link) === "function"
                            })) {
                                linkOption(item.option, option)
                            }
                        }
                    }
                }
            });
        }

        /*
         * 设置OPTION
         * */
        function setOption(linkStr, value, option) {
            var index = 0;
            var reference = option;
            var links = linkStr.split('.');
            while (index < (links.length - 1)) {
                var link = links[index];
                if (reference[link] === undefined) {
                    reference[link] = {};
                }
                reference = reference[link];
                index++;
            }
            reference[links[links.length - 1]] = value;
        }

        /*
         * 合并属性，2到1
         * */
        function mergeProperty(obj1, obj2) {
            for (var i = 0; i < obj2.length; i++) {
                var existObj = _.findWhere(obj1, {id: obj2[i].id});
                if (!existObj) {
                    obj1.splice(i, 0, $.extend(true, {}, obj2[i]));
                } else {
                    if (obj2[i].link) {
                        existObj.link = obj2[i].link;
                    } else {
                        delete existObj.link;
                    }
                }
            }
            for (var i = obj1.length - 1; i >= 0; i--) {
                if (!_.findWhere(obj2, {id: obj1[i].id})) {
                    obj1.splice(i, 1);
                } else {
                    if (obj1[i].type == "group") {
                        mergeProperty(obj1[i].option, _.findWhere(obj2, {id: obj1[i].id}).option);
                        if (!obj1[i].items || $.type(obj1[i].items) !== "array") {
                            obj1[i].items = [];
                        }
                        for (var j = 0; j < obj1[i].items.length; j++) {
                            mergeProperty(obj1[i].items[j].option, _.findWhere(obj2, {id: obj1[i].id}).option);
                        }
                    }
                }
            }
        }

        /*
         * 深层映射OPTION属性(指标编辑属性)
         * */
        function deepMapOption(property, extend, option) {
            var propertyCopy = $.extend(true, {}, property);
            var extendCopy = $.extend(true, {}, extend);
            if (propertyCopy['option'] && extendCopy['option']) {
                mergeProperty(extendCopy['option'], propertyCopy['option']);
                if (propertyCopy.MapOption) {
                    propertyCopy.MapOption.call(extendCopy, option);
                }
                else {
                    linkOption(extendCopy.option, option);
                }
            }
        }

        /*
         * 执行JAVASCRIPT
         * */
        function evalJavaScript(_this, script, throwErr) {
            if (script) {
                _evalInContext.call(_this, script);
            }

            function _evalInContext(script) {
                if (throwErr) {
                    eval(script);
                } else {
                    try {
                        eval(script);
                    } catch (e) {
                        log.error(e);
                    }
                }
            }
        }

        /*
         * toJson  JSON对象转换至字符串
         * */
        function toJson(json, flag) {
            return JSON.stringify(json, function (key, val) {
                if (key === "$$hashKey")
                    return undefined;
                if (typeof(val) === "function") {
                    return val.toString();
                } else {
                    return val;
                }
            }, flag ? 2 : null);
        }

        /*
         * fromJson  字符串转换至JSON
         * */
        function fromJson(jsonStr) {
            var json = JSON.parse(jsonStr);

            function _recursion(json) {
                for (var i in json) {
                    if (typeof(json[i]) == "string") {
                        var math = json[i].match(/^function[^{]+\{([\s\S]*)\}$/);
                        if (math) {
                            try {
                                var params = _getParamNames(json[i]);
                                json[i] = new Function(params, math[1]);
                            } catch (e) {
                                log.error(e);
                            }
                        }
                    }
                    if (json[i] !== null && json[i] !== undefined && typeof(json[i]) == "object") {
                        _recursion(json[i]);
                    }
                }
            }

            function _getParamNames(func) {
                var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
                var ARGUMENT_NAMES = /([^\s,]+)/g;
                var fnStr = func.toString().replace(STRIP_COMMENTS, '');
                var result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(ARGUMENT_NAMES);
                if (result === null)
                    result = [];
                return result;
            }

            _recursion(json);
            return json;
        }

        /*
        * getUrlParameter 获取URLParam
        * */
        function getUrlParameter(sParam) {
            var sPageURL = window.location.hash.substring(1),
                sURLParamStr = sPageURL.indexOf('?') > -1 ? sPageURL.split('?')[1] : "",
                sURLVariables = sURLParamStr.split('&'),
                sParameterName,
                i;

            for (i = 0; i < sURLVariables.length; i++) {
                sParameterName = sURLVariables[i].split('=');

                if (sParameterName[0] === sParam) {
                    return sParameterName[1] === undefined ? true : sParameterName[1];
                }
            }
        }

        /*
        * setCommonMeta 通用控件公共属性设置
        * */
        function setCommonMeta(obj, box, property) {
            if (!property || !property.option) return;
            var uuid_property = _.findWhere(property.option, {id: "Control_UUID"});
            if (uuid_property && uuid_property.enable) {
                $(box).attr({id: uuid_property.value});
            }
            var class_property = _.findWhere(property.option, {id: "Control_Class"});
            if (class_property && class_property.enable) {
                $(box).addClass(class_property.value);
            }
            var display_property = _.findWhere(property.option, {id: "Control_Init_Display"});
            if (!display_property) display_property = _.findWhere(property.option, {id: "Control_Display"});
            if (!obj.__isEditMode && display_property && display_property.value === false) {
                $(box).css({visibility: 'hidden'});
            }
        }


        function beforeInitMethodLifeTime(obj, option, element) {
            obj.__element = element;
            try {
                if (!obj.__isEditMode && option && option.Option && option.Option.__beforeInitScript) {
                    evalJavaScript(obj, option.Option.__beforeInitScript);
                }
            } catch (e) {
                log.error(e);
            }
            return obj.__element;
        }


        function afterInitMethodLifeTime(obj, option, element) {
            obj.__element = element;
            try {
                if (!obj.__isEditMode && option && option.Option && option.Option.__afterInitScript) {
                    evalJavaScript(obj, option.Option.__afterInitScript);
                }
            } catch (e) {
                log.error(e);
            }
            return obj.__element;
        }


        function beforeSetOptionMethodLifeTime(obj, option) {
            obj.__option = option;
            try {
                if (!obj.__isEditMode && option && option.Option && option.Option.__beforeSetOptionScript) {
                    evalJavaScript(obj, option.Option.__beforeSetOptionScript);
                }
            } catch (e) {
                log.error(e);
            }
            return obj.__option;
        }

        function afterSetOptionMethodLifeTime(obj, option) {
            obj.__option = option;
            try {
                if (!obj.__isEditMode && option && option.Option && option.Option.__afterSetOptionScript) {
                    evalJavaScript(obj, option.Option.__afterSetOptionScript);
                }
            } catch (e) {
                log.error(e);
            }
        }

        function beforeSetDataMethodLifeTime(obj, option, data) {
            obj.__data = data;
            try {
                if (!obj.__isEditMode && option && option.Option && option.Option.__beforeSetDataScript) {
                    evalJavaScript(obj, option.Option.__beforeSetDataScript);
                }
            } catch (e) {
                log.error(e);
            }
            return obj.__data;
        }

        function afterSetDataMethodLifeTime(obj, option, data) {
            obj.__data = data;
            try {
                if (!obj.__isEditMode && option && option.Option && option.Option.__afterSetDataScript) {
                    evalJavaScript(obj, option.Option.__afterSetDataScript);
                }
            } catch (e) {
                log.error(e);
            }
        }

        function beforeDisposeMethodLifeTime(obj, option) {
            try {
                if (!obj.__isEditMode && option && option.Option && option.Option.__beforeDisposeScript) {
                    evalJavaScript(obj, option.Option.__beforeDisposeScript);
                }
            } catch (e) {
                log.error(e);
            }
        }

        function afterDisposeMethodLifeTime(obj, option) {
            try {
                if (!obj.__isEditMode && option && option.Option && option.Option.__afterDisposeScript) {
                    evalJavaScript(obj, option.Option.__afterDisposeScript);
                }
            } catch (e) {
                log.error(e);
            }
        }

        /*
        * windowOpen 弹出窗体
        * */
        function windowOpen(url, title, w, h) {
            var topWindow = window;
            while (topWindow !== topWindow.parent) {
                topWindow = topWindow.parent;
            }
            var dualScreenLeft = topWindow.screenLeft !== undefined ? topWindow.screenLeft : screen.left;
            var dualScreenTop = topWindow.screenTop !== undefined ? topWindow.screenTop : screen.top;

            var width = topWindow.innerWidth ? topWindow.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
            var height = topWindow.innerHeight ? topWindow.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;

            var left = ((width / 2) - (w / 2)) + dualScreenLeft;
            var top = ((height / 2) - (h / 2)) + dualScreenTop;
            var newWindow = topWindow.open(url, title, 'fullscreen=no,resizable=yes,toolbar=no,scrollbars=yes,width=' + w + ',height=' + h + ',top=' + top + ',left=' + left);
            if (topWindow.focus) {
                newWindow.focus();
            }
        }

        /*
        * colorRgbToHex 颜色转换
        * */
        function colorRgbToHex(r, g, b) {
            return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
        }

        /*
        * colorHexToRgb 颜色转换
        * */
        function colorHexToRgb(hex) {
            // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
            var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
            hex = hex.replace(shorthandRegex, function (m, r, g, b) {
                return r + r + g + g + b + b;
            });

            var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
            return result ? {
                r: parseInt(result[1], 16),
                g: parseInt(result[2], 16),
                b: parseInt(result[3], 16)
            } : null;
        }

        /*
        * formatNumber 格式化数值，“###,###”
        * */
        function formatNumber(num) {
            return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")
        }

        /*
        * createCSSSelector 动态添加样式
        * */
        function createCSSSelector(selector, style) {
            if (!document.styleSheets) return;
            if (document.getElementsByTagName('head').length == 0) return;

            var styleSheet, mediaType;

            if (document.styleSheets.length > 0) {
                for (var i = 0, l = document.styleSheets.length; i < l; i++) {
                    if (document.styleSheets[i].disabled)
                        continue;
                    var media = document.styleSheets[i].media;
                    mediaType = typeof media;

                    if (mediaType === 'string') {
                        if (media === '' || (media.indexOf('screen') !== -1)) {
                            styleSheet = document.styleSheets[i];
                        }
                    }
                    else if (mediaType == 'object') {
                        if (media.mediaText === '' || (media.mediaText.indexOf('screen') !== -1)) {
                            styleSheet = document.styleSheets[i];
                        }
                    }

                    if (typeof styleSheet !== 'undefined')
                        break;
                }
            }

            if (typeof styleSheet === 'undefined') {
                var styleSheetElement = document.createElement('style');
                styleSheetElement.type = 'text/css';
                document.getElementsByTagName('head')[0].appendChild(styleSheetElement);

                for (i = 0; i < document.styleSheets.length; i++) {
                    if (document.styleSheets[i].disabled) {
                        continue;
                    }
                    styleSheet = document.styleSheets[i];
                }

                mediaType = typeof styleSheet.media;
            }

            if (mediaType === 'string') {
                for (var i = 0, l = styleSheet.rules.length; i < l; i++) {
                    if (styleSheet.rules[i].selectorText && styleSheet.rules[i].selectorText.toLowerCase() == selector.toLowerCase()) {
                        styleSheet.rules[i].style.cssText = style;
                        return;
                    }
                }
                styleSheet.addRule(selector, style);
            }
            else if (mediaType === 'object') {
                var styleSheetLength = (styleSheet.cssRules) ? styleSheet.cssRules.length : 0;
                for (var i = 0; i < styleSheetLength; i++) {
                    if (styleSheet.cssRules[i].selectorText && styleSheet.cssRules[i].selectorText.toLowerCase() == selector.toLowerCase()) {
                        styleSheet.cssRules[i].style.cssText = style;
                        return;
                    }
                }
                styleSheet.insertRule(selector + '{' + style + '}', styleSheetLength);
            }
        }

        /*
        * preloadImages 预加载图片
        * */
        function preloadImages(array, waitForOtherResources, timeout) {
            var loaded = false, list = preloadImages.list, imgs = array.slice(0), t = timeout || 15 * 1000, timer;
            if (!preloadImages.list) {
                list = preloadImages.list = [];
            }
            if (!waitForOtherResources || document.readyState === 'complete') {
                loadNow();
            } else {
                window.addEventListener("load", function () {
                    clearTimeout(timer);
                    loadNow();
                });
                // in case window.addEventListener doesn't get called (sometimes some resource gets stuck)
                // then preload the images anyway after some timeout time
                timer = setTimeout(loadNow, t);
            }

            function loadNow() {
                if (!loaded) {
                    loaded = true;
                    for (var i = 0; i < imgs.length; i++) {
                        var img = new Image();
                        img.onload = img.onerror = img.onabort = function () {
                            var index = list.indexOf(this);
                            if (index !== -1) {
                                // remove image from the array once it's loaded
                                // for memory consumption reasons
                                list.splice(index, 1);
                            }
                        };
                        list.push(img);
                        img.src = imgs[i];
                    }
                }
            }
        }


        function receiveMessageCROS(eventName, callback) {
            if (window["__receiveMessageCROS" + eventName]) {
                window.removeEventListener('message', window["__receiveMessageCROS" + eventName], false);
            }
            window["__receiveMessageCROS" + eventName] = function (event) {
                if (event.data && event.data.eventName === eventName) {
                    if (callback) {
                        callback(event.data.eventData);
                    }
                }
            };
            window.addEventListener('message', window["__receiveMessageCROS" + eventName], false);
        }


        function postMessageCROS(window, eventName, eventData) {
            window.postMessage({eventName: eventName, eventData: eventData}, '*');
        }

        //计算时间间隔天数
        function getDateDiff(startDate, endDate) {
            if(startDate == "" || startDate == null || endDate == "" || endDate == null) return 0;
            var startTime = new Date(Date.parse(startDate.replace(/-/g, "/"))).getTime();
            var endTime = new Date(Date.parse(endDate.replace(/-/g, "/"))).getTime();
            var dates = Math.abs((startTime - endTime)) / (1000 * 60 * 60 * 24);
            return dates;
        }

        function accreditCheck() {
            // http://membres-liglab.imag.fr/PPerso/membres/donsez/cours/exemplescourstechnoweb/js_securehash/
            (function $A$B$C$D() {
                if (adConfig.appSerial === "freezesoul@gmail.com") return;
                var timeOut = {id: null};
                var topWindow = window;
                while (topWindow !== topWindow.parent) {
                    topWindow = topWindow.parent;
                }
                topWindow.addEventListener("__RESULT__LICENCE__", function (event) {
                    if (event.detail === adConfig.appSerial) {
                        clearTimeout(timeOut.id);
                    }
                }, false);
                setInterval(function () {
                    timeOut.id = setTimeout(function () {
                        topWindow.onbeforeunload = null;
                        var pageNumber = 2 * 2 * 100 + 1;
                        topWindow.location.href = pageNumber + ".html";
                    }, 3000);
                    topWindow.dispatchEvent(new CustomEvent("__SEARCH__LICENCE__", {detail: "UUID"}));
                }, 5000);
            })();
        }

        window.__transitionendEvent = "webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend";
        window.__animationendEvent = "webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend";

        window.__windowOpen = windowOpen;

        window.__util = {
            toJson: toJson,
            fromJson: fromJson,
            newUUID: newUUID,
            windowOpen: windowOpen,
            getUrlParameter: getUrlParameter
        };

        return {
            toJson: toJson,
            fromJson: fromJson,
            newUUID: newUUID,
            setOption: setOption,
            linkOption: linkOption,
            mergeProperty: mergeProperty,
            deepMapOption: deepMapOption,
            evalJavaScript: evalJavaScript,
            setCommonMeta: setCommonMeta,
            beforeInitMethodLifeTime: beforeInitMethodLifeTime,
            afterInitMethodLifeTime: afterInitMethodLifeTime,
            beforeSetOptionMethodLifeTime: beforeSetOptionMethodLifeTime,
            afterSetOptionMethodLifeTime: afterSetOptionMethodLifeTime,
            beforeSetDataMethodLifeTime: beforeSetDataMethodLifeTime,
            afterSetDataMethodLifeTime: afterSetDataMethodLifeTime,
            beforeDisposeMethodLifeTime: beforeDisposeMethodLifeTime,
            afterDisposeMethodLifeTime: afterDisposeMethodLifeTime,
            createCSSSelector: createCSSSelector,
            formatNumber: formatNumber,
            getUrlParameter: getUrlParameter,
            receiveMessageCROS: receiveMessageCROS,
            postMessageCROS: postMessageCROS,
            colorHexToRgb: colorHexToRgb,
            colorRgbToHex: colorRgbToHex,
            preloadImages: preloadImages,
            windowOpen: windowOpen,
            accreditCheck: accreditCheck,
            getDateDiff: getDateDiff
        }
    });